//
// Created by mabinjie on 2024/10/29.
//

#ifndef PACKET_FACTORY_HPP
#define PACKET_FACTORY_HPP
#include <cstdint>
#include <memory>

#include "../message.hpp"

namespace protocol {

class PacketFactory;

typedef std::shared_ptr<PacketFactory> packet_factory_t;

class PacketFactory {
public:
    PacketFactory() = default;
    static packet_factory_t& factory(const std::string &id) {
        std::call_once(flag, []{
            factories = new std::unordered_map<std::string, packet_factory_t>();
        });

        if (factories->contains(id))
            return (*factories)[id];

        (*factories)[id] = std::make_shared<PacketFactory>();
        return (*factories)[id];
    }


    Packet packet(const jtt808_body_ptr& body, const MessageAttribute &attribute,
        const segmentation &segmentation = {}) {


        const auto header = std::make_shared<jtt808_header>(body, attribute, 1, "1234567890", message_sn_++, segmentation);

        return std::make_shared<jtt808_packet>(*header, body);
    }

    std::vector<Packet> packets(const std::vector<jtt808_body_ptr> &bodies, bool is_encrypted) {
        std::vector<Packet> packets;
        for (int i = 0; i < bodies.size(); ++i) {
            MessageAttribute attribute(true, is_encrypted, size(*bodies[i]));
            packets.push_back(packet(bodies[i], attribute, segmentation(bodies.size(), i+1)));
        }

        return packets;
    }

private:
    uint16_t message_sn_{0};
    static inline std::unordered_map<std::string, packet_factory_t> *factories = nullptr;
    static inline std::once_flag flag;
};

}

#endif //PACKET_FACTORY_HPP
